package com.base.components.database.dao.base;

import com.base.components.common.boot.SpringContextUtil;
import com.base.components.common.constants.sys.Pages;
import com.base.components.common.dto.page.DataPage;
import com.base.components.common.util.ColumnsUtil;
import com.base.components.common.util.ConvertUtil;
import org.hibernate.transform.ResultTransformer;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
import java.util.Map;

/**
 * JpaHelper
 * @author <a href="drakelee1221@gmail.com">LiGeng</a>
 * @version v1.0.0
 * @date 2019-01-24 9:21
 */
public abstract class JpaHelper {
  private static volatile EntityManager entityManager;

  public static EntityManager getEntityManager(){
    if (entityManager == null) {
      entityManager = SpringContextUtil.getBean(EntityManager.class);
    }
    return entityManager;
  }

  public static Query setMapResult(Query listQuery){
    listQuery.unwrap(org.hibernate.query.Query.class).setResultTransformer(AliasToEntityLinkedMapResultTransformer.INSTANCE);
    return listQuery;
  }

  public static Query setTransformerResult(Query listQuery, ResultTransformer resultTransformer){
    listQuery.unwrap(org.hibernate.query.Query.class).setResultTransformer(resultTransformer);
    return listQuery;
  }


  public static <E> DataPage<E> pageByQuery(Query countQuery, Query listQuery, Integer pageNum, Integer pageSize){
    int pageNum0 = Pages.Helper.pageNum(pageNum == null ? Pages.PAGE_NUM : pageNum);
    int pageSize0 = Pages.Helper.pageSize(pageSize == null ? Pages.PAGE_SIZE : pageSize);
    return pageByQueryNoHelper(countQuery, listQuery, pageNum0, pageSize0);
  }

  public static <E> DataPage<E> pageByQuery(Query countQuery, Query listQuery, Map<String, ?> pageParams){
    int pageNum = Pages.Helper.pageNum(ConvertUtil.convert(pageParams.get(Pages.PAGE_NUM_VAR_NAME), Pages.PAGE_NUM));
    int pageSize = Pages.Helper.pageSize(ConvertUtil.convert(pageParams.get(Pages.PAGE_SIZE_VAR_NAME), Pages.PAGE_SIZE));
    return pageByQueryNoHelper(countQuery, listQuery, pageNum, pageSize);
  }

  /** pageSize 无限制 */
  public static <E> DataPage<E> pageByQueryNoHelper(Query countQuery, Query listQuery, Map<String, ?> pageParams) {
    int pageNum = Pages.UnlimitedHelper.pageNum(ConvertUtil.convert(pageParams.get(Pages.PAGE_NUM_VAR_NAME), Pages.PAGE_NUM));
    int pageSize = Pages.UnlimitedHelper.pageSize(ConvertUtil.convert(pageParams.get(Pages.PAGE_SIZE_VAR_NAME), Pages.MAX));
    return pageByQueryNoHelper(countQuery, listQuery, pageNum, pageSize);
  }

  /** pageSize 无限制 */
  @SuppressWarnings("all")
  public static <E> DataPage<E> pageByQueryNoHelper(Query countQuery, Query listQuery, Integer pageNum, Integer pageSize) {
    DataPage<E> page = DataPage.getEmpty();
    long count = Long.parseLong(countQuery.getSingleResult().toString());
    if(count > 0){
      pageNum = Pages.UnlimitedHelper.pageNum(pageNum == null ? Pages.PAGE_NUM : pageNum);
      pageSize = Pages.UnlimitedHelper.pageSize(pageSize == null ? Pages.MAX : pageSize);
      listQuery.setFirstResult((pageNum - 1) * pageSize);
      listQuery.setMaxResults(pageSize);
      List<E> list = listQuery.getResultList();
      int pages = (int)count / pageSize;
      if (pages == 0) {
        pages = 1;
      } else {
        if ((count % pageSize) != 0) {
          pages++;
        }
      }
      page = new DataPage<>();
      page.setList(list);
      page.setPageNum(pageNum);
      page.setPageSize(pageSize);
      page.setTotal(count);
      page.setPages(pages);
    }
    return page;
  }

  /**
   * @see ColumnsUtil#findColumns(Class, String)
   */
  public static String findColumns(Class domainClass, String alias) {
    return ColumnsUtil.findColumns(domainClass, alias);
  }

  /**
   * @see ColumnsUtil#findColumns(Class)
   */
  public static Map<String, String> findColumns(Class domainClass) {
    return ColumnsUtil.findColumns(domainClass);
  }
}
